﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace TheOliver.Controls
{
    public class MicrosoftTranslator : UserControl, INotifyPropertyChanged
    {
        private string _appId;
        public string AppId
        {
            get { return _appId; }
            set { _appId = value; }
        }

        private bool _isBusy = false;
        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                _isBusy = value;
                OnPropertyChanged("IsBusy");
                this.IsIdle = !_isBusy;
            }
        }

        private bool _isIdle = true;
        public bool IsIdle
        {
            get { return _isIdle; }
            set
            {
                _isIdle = value;
                OnPropertyChanged("IsIdle");
            }
        }

        private byte[] _bytes;

        public MicrosoftTranslator()
        {
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                StackPanel sp = new StackPanel();
                sp.Background = new SolidColorBrush(Colors.Red);

                TextBlock tb = new TextBlock();
                tb.Text = "[Microsoft Translator Service]";

                sp.Children.Add(tb);
                this.Content = sp;
            }
        }

        public void Translate(string sourceText, string sourceLanguage, string targetLanguage)
        {
            if (this.AppId == string.Empty || this.AppId == null)
            {
                MessageBox.Show("No AppId for Translator service defined. You can get an AppId at http://dev.live.com.");
                return;
            }

            this.IsBusy = true;

            // Creating a string with the request URL
            // The URL includes the Bing developer appId and in this case hardcoded to translate from 
            // English to Spanish
            string translateUri =
                "http://api.microsofttranslator.com/V1/Http.svc/Translate?appId=" + _appId
                + "&from=" + sourceLanguage
                + "&to=" + targetLanguage;

            // Create a web request to the URL
            HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(translateUri);

            // Set the request method to POST
            httpWebRequest.Method = "POST";

            // Set the content type (needs to be text/plain for POST methods)
            httpWebRequest.ContentType = "text/plain";

            // Encode the txtInput value bytes for the POST
            _bytes = Encoding.UTF8.GetBytes(sourceText);

            // Create a stream for the request
            httpWebRequest.BeginGetRequestStream(new AsyncCallback(OnGetRequestStream), httpWebRequest);
        }

        private void OnGetRequestStream(IAsyncResult iar)
        {
            try
            {
                HttpWebRequest httpWebRequest = (HttpWebRequest)iar.AsyncState;
                Stream os = httpWebRequest.EndGetRequestStream(iar);

                os.Write(_bytes, 0, _bytes.Length);

                if (os != null)
                {
                    // Close the stream when finished
                    os.Close();
                }

                // Send the request and get the response
                httpWebRequest.BeginGetResponse(new AsyncCallback(OnGetResponse), httpWebRequest);
            }
            catch (Exception exc)
            {
                RaiseError(exc);
            }
        }

        private void OnGetResponse(IAsyncResult iar)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)iar.AsyncState;

                if (!iar.IsCompleted)
                {
                    Debug.WriteLine("Not completed");
                }
                WebResponse response = request.EndGetResponse(iar);

                // Open a stream for the response
                Stream stream = response.GetResponseStream();
                StreamReader reader = new StreamReader(stream);

                // Create a string for the contents of the web response
                string output = reader.ReadToEnd();

                // Return the output string
                OnTranslated(output);
            }
            catch (Exception exc)
            {
                RaiseError(exc);
            }
        }

        public event TranslatorEventHandler Translated;
        public event TranslatorErrorEventHandler TranslationError;

        private void OnTranslated(string output)
        {
            this.IsBusy = false;
            if (Translated != null)
            {
                Dispatcher.BeginInvoke(() =>
                    {
                        TranslatorEventArgs args = new TranslatorEventArgs();
                        args.TranslatedText = output;
                        Translated(this, args);
                    });
            }
        }

        private void RaiseError(Exception exc)
        {
            this.IsBusy = false;
            if (TranslationError != null)
            {

                Dispatcher.BeginInvoke(() =>
                    {
                        TranslatorErrorEventArgs args = new TranslatorErrorEventArgs();
                        args.Error = exc;
                        TranslationError(this, args);
                    });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                Dispatcher.BeginInvoke(() =>
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    });
            }
        }
    }

    public delegate void TranslatorEventHandler(object sender, TranslatorEventArgs args);

    public class TranslatorEventArgs : EventArgs
    {
        public string TranslatedText { get; set; }
    }

    public delegate void TranslatorErrorEventHandler(object sender, TranslatorErrorEventArgs args);

    public class TranslatorErrorEventArgs
    {
        public Exception Error { get; set; }
    }
}
